package core.algorithms;

import java.util.ArrayList;
import java.util.List;

import core.interfaces.IBooleanOperator;
import core.interfaces.IState;

public class RandomWalkHillClimbing<T> extends HillClimbing<T>
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 2676140963713527318L;
	//Members:
	private int m_RandomSteps;

	public RandomWalkHillClimbing(SearchParameters<T> searchParameters)
	{
		super(searchParameters);

//		this.m_FinalResult = -1;
	}
	@Override
	public void initAlgorithm(SearchParameters<T> searchParameters)
	{
		super.initAlgorithm(searchParameters);

		this.m_RandomSteps = searchParameters.getRandomSteps();
		m_SearchResults = new SearchResults<T>(null, -1, false, 0);
	}
	public SearchResults<T> doAlgorithm(IState<T> initialState)
	{
		IState<T> currentState = initialState;
		while (isDoAnotherIteration(m_SearchParameters.isBoundHeuristicCalls()))
		{
			double currentHeuristicValue = callHeuristicFunction(currentState);
			double bestVal = currentHeuristicValue;
			
		
			saveBestState(currentState, currentHeuristicValue);
			
			// go over all the neighbors of the current node
			// look for the next best neighbor
			List<IBooleanOperator> bestOperators = new ArrayList<IBooleanOperator>();
			List<? extends IBooleanOperator> possibleOperators = currentState.getPossibleOperators();
			bestVal = findBestOperator(currentState, bestVal, bestOperators, possibleOperators);
			
			//decide on next step
			if (bestVal <= currentHeuristicValue)
			{
				//random walk
				doRandomWalk(currentState);
			}
			else
			{
				// continue to the next iteration
				currentState = getRandom(bestOperators, currentState);
				
			}
			
			currentHeuristicValue = callHeuristicFunction(currentState) ;
			super.stepFinished();
				//m_Heuristic.getValue(currentState);
		}
		return new SearchResults<T>(
				getSearchResults().getFinalState(),
				getSearchResults().getFinalStateValue(),
				(m_StepsTaken == getSearchParameters().getMaximumHeuristicCalls()),
				m_StepsTaken);
	}

	
	
	private void doRandomWalk(IState<T> currentState) 
	{
		//randomly walk on the graph
		for(int i=0; i<m_RandomSteps; i++)
		{
			List<? extends IBooleanOperator> possibleOperators = currentState.getPossibleOperators();
			int operatorIndex = m_Randomizer.nextInt(possibleOperators.size());
			currentState.doOperator(possibleOperators.get(operatorIndex)); 	
		}
//		if(currentState.shortcutOperatorExists())
//		{
//			currentState.doShortcutOperator();			
//		}
	}

	@Override
	public String getAlgorithmName()
	{
		return "RANDOM WALK HC";
	}
}
